﻿#include "module_base.h"

#define   MAX_TEXT_1024     10240
char    g_convTemp[MAX_TEXT_1024];
wchar_t g_convTempW[MAX_TEXT_1024];

//-------------------------------
CXBytes::CXBytes()
{
	Init();
}

CXBytes::CXBytes(const CXBytes& _that)
{
	Init();

	alloc(_that._length);
	if(_that._length >0)
		memcpy_s(_data, _that._length, _that._data, _that._length);
}

CXBytes::CXBytes(CXBytes&& _that)
{
	_that.move();
	_bOwner = TRUE;
	_data = _that._data;
	_length = _that._length;
}

CXBytes::CXBytes(const wchar_t* pText)
{
	Init();
	int size = wcslen(pText) * 2;
	set((void*)pText, size);
}

CXBytes::CXBytes(const char* pText)
{
	Init();
	int size = strlen(pText);
	set((void*)pText, size);
}

void CXBytes::operator=(const wchar_t* pText)
{
	Init();
	int size = wcslen(pText)*2;
	set((void*)pText, size);
}

void CXBytes::operator=(const char* pText)
{
	Init();
	int size = strlen(pText);
	set((void*)pText, size);
}

CXBytes::~CXBytes()
{
	if (_bOwner && _data) free(_data);
}

void CXBytes::Init()
{
	_bOwner = TRUE;
	_data = NULL;
	_length = 0;
}

void CXBytes::operator=(const CXBytes &_that)
{
	if (_bOwner && _data) free(_data);

	_bOwner = TRUE;
	alloc(_that._length);
	memcpy_s(_data, _that._length, _that._data, _that._length);
}

void CXBytes::operator=(CXBytes&& _that)
{
	if (_bOwner && _data) free(_data);

	_bOwner = TRUE;
	_data = _that._data;
	_length = _that._length;
	_that.move();
}

BOOL CXBytes::operator==(const CXBytes& _that)
{
	if (_length != _that._length)
		return FALSE;

	for (int i =0; i<_length ;i++)
	{
		if (_data[i] != _that._data[i])
			return FALSE;
	}
	return TRUE;
}

CXBytes CXBytes::operator+(const CXBytes& _that)
{
	CXBytes  bytes = *this;
	bytes.add(_that._data, _that._length);
	return bytes;
}

void CXBytes::operator+=(const CXBytes& _that)
{
	add(_that._data, _that._length);
}

BYTE CXBytes::operator[](int pos)
{
	if (pos < 0 || pos >= _length) return 0;

	return  _data[pos];
}

char* CXBytes::alloc(UINT length)
{
	if (_bOwner && _data) free(_data);

	_length = length;
	if (length > 0)
	{
		_data = (char*)malloc(length+2);
		memset(_data, 0, length);
		_bOwner = TRUE;

		_data[length] = 0;
		_data[length + 1] = 0;
	} else
	{
		_length = 0;
		_data = NULL;
		_bOwner = TRUE;
	}
	return _data;
}

//在原有基础上增加大小
void CXBytes::addSize(UINT length)
{
	if (length <= 0) return ;

	int  total_length = _length + length;
	char* data_new = (char*)malloc(total_length+2);
	memset(data_new + _length, 0, length);

	if (_length > 0)
	{
		memcpy_s(data_new, total_length, _data, _length);
	}
	data_new[total_length] = 0;
	data_new[total_length + 1] = 0;

	if(_bOwner && _data) //释放旧数据
		free(_data);

	_bOwner = TRUE;
	_data = data_new;
	_length = total_length;
}

void CXBytes::add(void* data, int length)
{
	if (NULL == data || length <= 0) return;
	int length_old = _length;
	addSize(length);
	memcpy_s(_data + length_old, _length, data, length);
}

void CXBytes::addText(const wchar_t* pText)
{
	if (NULL == pText) return;
	int length = wcslen(pText);
	if (length <= 0) return;
	length = length * 2;

	int length_old = _length;
	addSize(length);

	memcpy_s(_data + length_old, _length, pText, length);
}

void CXBytes::addTextA(const char* pText)
{
	if (NULL == pText) return;
	int length = strlen(pText);
	if (length <= 0) return;

	int length_old = _length;
	addSize(length);

	memcpy_s(_data + length_old, _length, pText, length);
}

void CXBytes::addInt(int value_)
{
	add(&value_, 4);
}

void CXBytes::addUInt(unsigned int value_)
{
	add(&value_, 4);
}

void CXBytes::addShort(short value_)
{
	add(&value_, 2);
}

void CXBytes::addUShort(unsigned short value_)
{
	add(&value_, 2);
}

void CXBytes::addFloat(float value_)
{
	add(&value_, 4);
}

void CXBytes::addDouble(double value_)
{
	add(&value_, 8);
}

void CXBytes::addWchar(wchar_t value_)
{
	add(&value_, 2);
}

void CXBytes::addByte(BYTE value_)
{
	add(&value_, 1);
}

void CXBytes::setHexText(const wchar_t* pHex)
{
	clear();
	addHex(pHex);
}

BYTE CXBytes::hexCharToByte(wchar_t c)
{
	if (c >= L'0' && c <= L'9') return (c - L'0');
	if (c >= L'A' && c <= L'F') return (c - L'A' + 10);
	if (c >= L'a' && c <= L'f') return (c - L'a' + 10);
	return 0;
}

BOOL CXBytes::addHex(const wchar_t* pHex)
{
	if (NULL == pHex) return FALSE;
	
	int length_old = _length;
	int length =wcslen(pHex);

	int size = length / 2;
	if (0 != length % 2)
		addSize(size+1);
	else
		addSize(size);

	int index = 0;
	BYTE  byte_ = 0;
	char* p = _data + length_old;
	for (int i =0; i<size; i++)
	{
		index = i * 2;
		byte_ = hexCharToByte(pHex[index]);
		byte_ = byte_ << 4;
		byte_ |= hexCharToByte(pHex[index +1]);

		*p = byte_;
		p++;
	}
	if (0 != length % 2)
	{
		index = size * 2;
		byte_ = hexCharToByte(pHex[index]);
		byte_ = byte_ << 4;
		*p = byte_;
	}
	return TRUE;
}

CXText  CXBytes::getHexToText()
{
	CXText  text;
	wchar_t  hexs[17] = L"0123456789ABCDEF";
	wchar_t ch;
	wchar_t buf[20] = {0};
	for (int i=0; i< _length; i++)
	{
		BYTE index = (_data[i] >> 4) & 0xf;

		ch = hexs[index];
		text += ch;

		index = _data[i] &0xf;
		ch = hexs[index];

		text += ch;
	}
	return text;
}


const wchar_t* CXBytes::getTextPtr()
{
	return (const wchar_t*)_data;
}

const char* CXBytes::getTextPtrA()
{
	return (const char*)_data;
}

int CXBytes::getInt(int pos)
{
	if (_length < 4) return 0;

	if (pos > (_length - 4))
		pos = _length - 4;
	if (pos < 0) pos = 0;

	return *(int*)(_data+pos);
}

unsigned int CXBytes::getUInt(int pos)
{
	if (_length < 4) return 0;

	if (pos > (_length - 4))
		pos = _length - 4;
	if (pos < 0) pos = 0;

	return *(unsigned int*)(_data + pos);
}

short CXBytes::getShort(int pos)
{
	if (_length < 2) return 0;

	if (pos > (_length - 2))
		pos = _length - 2;
	if (pos < 0) pos = 0;

	return *(short*)(_data + pos);
}

unsigned short CXBytes::getUShort(int pos)
{
	if (_length < 2) return 0;

	if (pos > (_length - 2))
		pos = _length - 2;
	if (pos < 0) pos = 0;

	return *(unsigned short*)(_data + pos);
}

float CXBytes::getFloat(int pos)
{
	if (_length < 4) return 0;

	if (pos > (_length - 4))
		pos = _length - 4;
	if (pos < 0) pos = 0;

	return *(float*)(_data + pos);
}

double CXBytes::getDouble(int pos)
{
	if (_length < 8) return 0;

	if (pos > (_length - 8))
		pos = _length - 8;
	if (pos < 0) pos = 0;

	return *(double*)(_data + pos);
}

wchar_t CXBytes::getWchar(int pos)
{
	if (_length < 1) return 0;

	if (pos > (_length - 1))
		pos = _length - 1;
	if (pos < 0) pos = 0;

	return *(wchar_t*)(_data + pos);
}

BYTE CXBytes::getByte(int pos)
{
	if (_length < 1) return 0;

	if (pos > (_length - 1))
		pos = _length - 1;
	if (pos < 0) pos = 0;

	return *(BYTE*)(_data + pos);
}

void CXBytes::clear()
{
	if (_bOwner && _data) free(_data);
	
	_length = 0;
	_data = NULL;
	_bOwner = TRUE;
}

void CXBytes::set(void* data, int length)
{
	alloc(length);
	if(length>0)
		memcpy_s(_data, _length, data, length);
}

void CXBytes::setText(const wchar_t* pText)
{
	if (NULL == pText) return;
	int length = wcslen(pText)*2;
	alloc(length);
	if (length > 0)
		memcpy_s(_data, _length, pText, length);
}

void CXBytes::setTextA(const char* pText)
{
	if (NULL == pText) return;
	int length = strlen(pText);
	alloc(length);
	if (length > 0)
		memcpy_s(_data, _length, pText, length);
}

CXBytes CXBytes::getLeft(int length)
{
	CXBytes bytes;
	if (length > 0)
	{
		int size = min(_length, length);
		if (size > 0)
			bytes.set(_data, size);
	}
	return bytes;
}

CXBytes CXBytes::getRight(int length)
{
	CXBytes bytes;
	if (length > 0)
	{
		int size = length;
		if (length > _length)
			size = _length;

		if (size > 0)
			bytes.set(_data + (_length - size), size);
	}
	return bytes;
}

CXBytes CXBytes::getMid(int iStart, int length)
{
	CXBytes bytes;
	if (length > 0)
	{
		int size = length;
		if (size > (_length - iStart))
			size = _length - iStart;

		if (size > 0)
			bytes.set(_data + iStart, size);
	}
	return bytes;
}

//----------------------------------------------------
CXText::CXText()
{
	_bOwner = TRUE; _text = new wstring;
}

CXText::CXText(const CXText& _that)
{
	_bOwner = TRUE;
	_text = new std::wstring;
	*_text = *_that._text;
}

CXText::CXText(CXText&& _that)
{
	_that.move();
	_bOwner = TRUE;
	_text = _that._text;
}

CXText::CXText(CXBytes &_that)
{
	_text = new std::wstring;
	_bOwner = TRUE;

	int size = _that.size()/2;
	if (size > 0)
	{
		_text->resize(size + 1);
		wmemcpy_s((wchar_t*)_text->data(), size + 1, (wchar_t*)_that.get(), size);
		_bOwner = TRUE;
	}
}

void CXText::operator=(CXBytes &_that)
{
	int size = _that.size()/2;
	if (size > 0)
	{
		if(FALSE==_bOwner || NULL== _text)
			_text = new std::wstring;
		_text->resize(size + 1);
		wmemcpy_s((wchar_t*)_text->data(), size + 1, (wchar_t*)_that.get(), size);
		_bOwner = TRUE;
	} else
	{
		_text = NULL;
		_bOwner = FALSE;
	}
}

//-------------------------------------
CXTextA::CXTextA()
{
	_bOwner = TRUE; _text = new string;
}

CXTextA::CXTextA(const CXTextA& _that)
{
	_bOwner = TRUE;
	_text = new std::string;
	*_text = *_that._text;
}

CXTextA::CXTextA(CXTextA&& _that)
{
	_that.move();
	_bOwner = TRUE;
	_text = new std::string;
	_text = _that._text;
}

CXTextA::CXTextA(CXBytes &_that)
{
	_text = new std::string;
	_bOwner = TRUE;

	int size = _that.size();
	if (size > 0)
	{
		_text->resize(size + 1);
		memcpy_s((void*)_text->data(), size + 1, _that.get(), size);
		_bOwner = TRUE;
	}
}

void CXTextA::operator=(CXBytes &_that)
{
	if (_bOwner) delete _text;

	int size = _that.size();
	if (size > 0)
	{
		_text = new std::string;
		_text->resize(size+1);
		memcpy_s((void*)_text->data(), size+1, _that.get(), size);
		_bOwner = TRUE;

	} else
	{
		_text = NULL;
		_bOwner = FALSE;
	}
}

//--------------------------------------
CXFile::CXFile()
{
	m_pFile = NULL;
}

CXFile::~CXFile()
{
	if (m_pFile) fclose(m_pFile);
}

BOOL CXFile::open(const wchar_t* pFileName)
{
	int err = _wfopen_s(&m_pFile, pFileName, L"ab+");
	if (0 == err)
		return TRUE;
	return FALSE;
}

//打开文件, 只读模式
BOOL CXFile::openRead(const wchar_t* pFileName)
{
	if (0 == _wfopen_s(&m_pFile, pFileName, L"rb"))
		return TRUE;
	return FALSE;
}

//打开一个空的文件进行读写。如果该文件存在，其内容将被销毁。
BOOL CXFile::openWrite(const wchar_t* pFileName)
{
	if (0 == _wfopen_s(&m_pFile, pFileName, L"w+"))
		return TRUE;
	return FALSE;
}

//打开文件, 指定打开方式
BOOL CXFile::openEx(const wchar_t* pFileName, const wchar_t* pMode)
{
	if (0 == _wfopen_s(&m_pFile, pFileName, pMode))
		return TRUE;
	return FALSE;
}

void CXFile::close()
{
	fclose(m_pFile);
}

UINT  CXFile::getLength()
{
	long length = 0;
	fseek(m_pFile, 0, SEEK_END);
	length = ftell(m_pFile);
	fseek(m_pFile, 0, SEEK_SET);
	return length;
}

BOOL CXFile::seekBegin()
{
	if (0 == fseek(m_pFile, 0, SEEK_SET))
		return TRUE;
	return FALSE;
}

BOOL CXFile::seekEnd()
{
	if (0 == fseek(m_pFile, 0, SEEK_END))
		return TRUE;
	return FALSE;
}

BOOL CXFile::seekPos(int offset, int origin)
{
	if (0 == fseek(m_pFile, offset, origin))
		return TRUE;
	return FALSE;
}

//返回实际读取长度
UINT CXFile::readData(out_ void *buf, in_ int nBufSize)
{
	int size = getLength();
	if (nBufSize > size)
		nBufSize = size;
	return fread(buf, 1, nBufSize, m_pFile);
}

BOOL CXFile::readDataRow(out_ char* buf, in_ int nBufSize)
{
	if (fgets(buf, nBufSize, m_pFile))
		return TRUE;
	return FALSE;
}

CXBytes CXFile::readDataBytes(int nLength)
{
	if (-1 == nLength)
		nLength = getLength();
	CXBytes  bytes;
	if (nLength > 0)
	{
		const char* data = bytes.alloc(nLength);
		fread((void*)data, 1, nLength, m_pFile);
	}
	return bytes;
}

UINT CXFile::writeData(const void* buf, int nLength)
{
	return fwrite(buf, 1, nLength, m_pFile);
}

UINT CXFile::writeTextPtr(const wchar_t* data, int nLength)
{
	if (-1 == nLength)  nLength = wcslen(data);
	return fwrite(data, 2, nLength, m_pFile);
}

UINT CXFile::writeTextPtrA(const char* data, int nLength)
{
	if (-1 == nLength)  nLength = strlen(data);
	return fwrite(data, 1, nLength, m_pFile);
}

UINT CXFile::writeText(CXText text, int nLength)
{
	if (!text.empty())
	{
		if (-1 == nLength) nLength = text.size();
		return fwrite(text.get(), 2, nLength, m_pFile);
	}
	return 0;
}

UINT CXFile::writeTextA(CXTextA text, int nLength)
{
	if (!text.empty())
	{
		if (-1 == nLength) nLength = text.size();
		return fwrite(text.get(), 1, nLength, m_pFile);
	}
	return 0;
}

BOOL CXFile::isEof()
{
	if(feof(m_pFile))
		return  TRUE;
	return FALSE;
}

//------------------------------------------------
CXText XC_GetRunDir()
{
	wchar_t  buf[MAX_PATH] = { 0 };
	GetModuleFileName(NULL, buf, MAX_PATH);
	wchar_t*  p = wcsrchr(buf, L'\\');
	if(p)  *p = 0;
	CXText  text = buf;
	return text;
}

CXText XC_GetCurrentDir()
{
	wchar_t  buf[MAX_PATH] = { 0 };
	GetCurrentDirectory(MAX_PATH, buf);
	CXText text = buf;
	return text;
}

CXText XC_GetRunFileName()
{
	wchar_t  buf[MAX_PATH] = { 0 };
	GetModuleFileName(NULL, buf, MAX_PATH);
	CXText text = buf;
	return text;
}

CXText XC_GetEnvironmentVariable(const wchar_t* pName)
{
	wchar_t  buf[4096] = { 0 };
	GetEnvironmentVariable(pName, buf, 4096);
	CXText text = buf;
	return text;
}

void  XC_MsgBox(const wchar_t* pText, const wchar_t* pCaption)
{
	MessageBox(NULL, pText, pCaption,0);
}

//------------------------------------------------
BOOL xc_createFolders(const wchar_t*  pPath)
{
	if (NULL == pPath)return FALSE;
	wchar_t fullPath[MAX_PATH] = { 0 };
	wcscpy_s(fullPath, MAX_PATH, pPath);

	int len = wcslen(fullPath);
	if (!(L'\\' == fullPath[len - 1] || L'/' == fullPath[len - 1]))
	{
		const wchar_t*   pEnd = wcsrchr(fullPath, L'\\');
		if (NULL == pEnd) pEnd = wcsrchr(fullPath, L'/');
		if (NULL == pEnd) return FALSE;

		pEnd = wcschr(pEnd, L'.');
		if (NULL == pEnd)  //末尾是文件夹
		{
			if ((len + 1) >= MAX_PATH) return FALSE;
			fullPath[len] = L'\\';
			fullPath[len + 1] = 0;
		}
	}

	const wchar_t* p = wcsstr(fullPath, L":\\");
	if (NULL == p) p = wcsstr(fullPath, L"://");

	if (NULL == p) return FALSE;
	if (p) p += 2;

	wchar_t buf[MAX_PATH] = { 0 };
	while (*p)
	{
		if (L'\\' == *p || L'/' == *p)
		{
			int len = p - fullPath;
			if (len < 1 || len >= MAX_PATH)
				return FALSE;
			wmemcpy_s(buf, MAX_PATH, fullPath, len);
			if (0 != _waccess_s(buf, 0))
			{
				if (-1 == _wmkdir(buf))
				{
					if (EEXIST != errno)
					{
						return FALSE;
					}
				}
			}
		}
		p++;
	}
	return TRUE;
}

BOOL xc_copyFile(const wchar_t* dest, const wchar_t*  src)
{
	wchar_t  dir[MAX_PATH] = { 0 };
	wmemcpy_s(dir, MAX_PATH, dest, wcslen(dest));
	//PathRemoveFileSpec(dir); 
	if (xc_createFolders(dir))
		return ::CopyFile(src, dest, TRUE);
	return FALSE;
}

//-------------------------------------------------
//UTF8 到 UNICODE
CXText U2W(const char *utf8, int length)
{
	CXText  text;
	int nNeedLen = MultiByteToWideChar(CP_UTF8, 0, utf8, length, NULL, 0);
	if (nNeedLen > 0)
	{
		text.resize(nNeedLen);
		nNeedLen = MultiByteToWideChar(CP_UTF8, 0, utf8, length, (wchar_t*)text.get(), nNeedLen);
	}
	return text;
}

//UNICODE 到 UTF8 字节集
CXBytes W2U(const wchar_t *pString, int length)
{
	if (-1 == length) length = wcslen(pString);
	CXBytes  bytes;
	int nNeedLen = WideCharToMultiByte(CP_UTF8, NULL, pString, length, NULL, 0, NULL, NULL);
	if (nNeedLen > 0)
	{
		bytes.alloc(nNeedLen);
		nNeedLen = WideCharToMultiByte(CP_UTF8, NULL, pString, length, bytes.get(), nNeedLen, NULL, NULL);
	}
	return bytes;
}

CXTextA W2A_(const wchar_t* pString, int length)
{
	CXTextA  text;
	if (-1 == length) length = wcslen(pString);
	int nNeedLen = WideCharToMultiByte(CP_ACP, NULL, pString, length, NULL, 0, NULL, NULL);
	if (nNeedLen > 0)
	{	
		text.resize(nNeedLen);
		WideCharToMultiByte(CP_ACP, NULL, pString, nNeedLen, (char*)text.get(), nNeedLen, NULL, NULL);
	}
	return text;
}


CXText  A2W_(const char* pString, int length)
{
	CXText  text;
	if (-1 == length) length = strlen(pString);
	int nNeedLen = MultiByteToWideChar(CP_ACP, 0, pString, length, NULL,0 );
	if (nNeedLen > 0)
	{
		text.resize(nNeedLen);
		MultiByteToWideChar(CP_ACP, 0, pString, length, (wchar_t*)text.get(), nNeedLen);
	}
	return text;
}

const char* W2A_temp(const wchar_t* pString)
{
	g_convTemp[0] = 0;
	if (pString)
	{
		int len = WideCharToMultiByte(CP_ACP, NULL, pString, -1, g_convTemp, MAX_TEXT_1024 - 1, NULL, NULL);
		if (len <= 0)
			return "";
	}
	return g_convTemp;
}

const wchar_t* A2W_temp(const char* pString)
{
	g_convTempW[0] = 0;
	if (pString)
	{
		int len = MultiByteToWideChar(CP_ACP, 0, pString, -1, g_convTempW, MAX_TEXT_1024 - 1);
		if (len <= 0)
			return L"";
	}
	return g_convTempW;
}

//-------------------------------------
const char* XC_itoa_temp(int nValue)
{
	sprintf_s(g_convTemp, MAX_TEXT_1024, "%d", nValue);
	return g_convTemp;
}

const wchar_t* XC_itow_temp(int nValue)
{
	swprintf_s(g_convTempW, MAX_TEXT_1024, L"%d", nValue);
	return g_convTempW;
}

const wchar_t* XC_i64tow_temp(__int64 nValue)
{
	swprintf_s(g_convTempW, MAX_TEXT_1024, L"%I64d", nValue);
	return g_convTempW;
}

const char*    XC_ftoa_temp(float fValue)
{
	sprintf_s(g_convTemp, MAX_TEXT_1024, "%f", fValue);
	return g_convTemp;
}

const wchar_t* XC_ftow_temp(float fValue)
{
	swprintf_s(g_convTempW, MAX_TEXT_1024, L"%.2f", fValue);
	return g_convTempW;
}

const wchar_t* XC_fftow_temp(double fValue)
{
	swprintf_s(g_convTempW, MAX_TEXT_1024, L"%.2f", fValue);
	return g_convTempW;
}

const wchar_t* XC_itohex_temp(int value_)
{
	swprintf_s(g_convTempW, L"0x%08X", value_);
	return g_convTempW;
}

//-----------------------------------------
CSysDateTime::CSysDateTime()
{
	__time64_t time_;
	_time64(&time_);
	_localtime64_s(&m_tm, &time_);
}

int CSysDateTime::getYear()
{
	return m_tm.tm_year + 1900;
}

int CSysDateTime::getMonth()
{
	return m_tm.tm_mon + 1;
}

int CSysDateTime::getDay()
{
	return m_tm.tm_mday;
}

int CSysDateTime::getHour()
{
	return m_tm.tm_hour;
}

int CSysDateTime::getMinute()
{
	return m_tm.tm_min;
}

int CSysDateTime::getSecond()
{
	return m_tm.tm_sec;
}

int CSysDateTime::getDayOfWeek()
{
	return m_tm.tm_wday;
}

//------------------------------------------------
const wchar_t* GetTimeString_temp(const wchar_t *format)
{
	__time64_t time_;
	_time64(&time_);

	tm tm_;
	_localtime64_s(&tm_, &time_);

	wcsftime(g_convTempW, MAX_TEXT_1024, format, &tm_);
	return g_convTempW;
}

const wchar_t* GetTime_temp()
{
	__time64_t time_;
	_time64(&time_);

	tm tm_;
	_localtime64_s(&tm_, &time_);
	//[%Y-%m-%d %X]
	wcsftime(g_convTempW, MAX_TEXT_1024, L"%Y-%m-%d %H:%M:%S", &tm_);
	return g_convTempW;
}

const wchar_t* GetDate_temp()
{
	__time64_t time_;
	_time64(&time_);

	tm tm_;
	_localtime64_s(&tm_, &time_);

	wcsftime(g_convTempW, MAX_TEXT_1024, L"%Y-%m-%d", &tm_);
	return g_convTempW;
}

int GetDayInMonth(int y, int m)
{
	int d;
	int day[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
	if (2 == m)
	{
		d = (((0 == y % 4) && (0 != y % 100) || (0 == y % 400)) ? 29 : 28);
	} else
	{
		d = day[m - 1];
	}
	return d;
}
